package com.example.chainsave.fabric.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.chainsave.common.model.Result;
import com.example.chainsave.fabric.model.FileMetadata;
import com.example.chainsave.fabric.model.PartitionMetadata;
import org.hyperledger.fabric.gateway.*;
import org.springframework.stereotype.Service;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

/**
 * @Author WaleGarrett
 * @Date 2022/3/9 21:08
 */
@Service
public class FileMetadataService {

    //getting connected to the gateway
    public static Gateway connect() throws Exception {
        // Load a file system based wallet for managing identities.
        Path walletPath = Paths.get("src", "main", "resources", "wallet");
        Wallet wallet = Wallets.newFileSystemWallet(walletPath);
        // load a CCP
        Path networkConfigPath = Paths.get("src", "main", "resources", "connection.json");

        Gateway.Builder builder = Gateway.createBuilder();
        builder.identity(wallet, "appUser").networkConfig(networkConfigPath).discovery(false);
        return builder.connect();
    }

    /**
     * 文件元数据上链
     *
     * @return
     * @throws Exception
     */
    public static Result<FileMetadata> createFileMetadata(FileMetadata fileMetadata) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.submitTransaction("CreateFileMetadata", String.valueOf(fileMetadata.getUserId()),
                fileMetadata.getFileHash(), fileMetadata.getFileMd5(), fileMetadata.getFileName(),
                fileMetadata.getFileDescription(), String.valueOf(fileMetadata.getPartitionNum()),
                String.valueOf(fileMetadata.getDuplicateNum()),
                JSON.toJSONString(fileMetadata.getAllPartitionIds()));

        String resJson = new String(result, "UTF-8");
        JSONObject jsonObject = JSON.parseObject(resJson);
        int code = jsonObject.getInteger("code");
        String msg = jsonObject.get("msg").toString();
        String fileMetadataJson = jsonObject.get("data").toString();
        FileMetadata responseData = JSONObject.parseObject(fileMetadataJson, FileMetadata.class);
//      FileMetadata responseData = (code == 200) ? JSONObject.parseObject(fileMetadataJson, FileMetadata.class) : null;
        return new Result<FileMetadata>().setCode(code).setMessage(msg).setData(responseData);
    }


    /**
     * 根据文件元数据Id查询文件元数据
     *
     * @param fileMetadataId
     * @return
     * @throws Exception
     */
    public static Result<FileMetadata> queryFileMetadataById(int fileMetadataId) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.evaluateTransaction("QueryFileMetadataByFileMetaId", String.valueOf(fileMetadataId));

        String resJson = new String(result, "UTF-8");

        System.out.println("resJson:" + resJson);

        JSONObject jsonObject = JSON.parseObject(resJson);
        int code = jsonObject.getInteger("code");
        String msg = jsonObject.get("msg").toString();
        String fileMetadataJson = jsonObject.get("data").toString();
        FileMetadata responseData = JSONObject.parseObject(fileMetadataJson, FileMetadata.class);
//      FileMetadata responseData = (code == 200) ? JSONObject.parseObject(fileMetadataJson, FileMetadata.class) : null;
        return new Result<FileMetadata>().setCode(code).setMessage(msg).setData(responseData);

    }

    /**
     * 根据MD5值查询文件元数据列表
     *
     * @param fileMd5
     * @return
     * @throws Exception
     */
    public static Result<List<FileMetadata>> queryFileMetadataByMd5(String fileMd5) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.evaluateTransaction("QueryFileMetadataByMd5", fileMd5);


        String resJson = new String(result, "UTF-8");
        JSONObject jsonObject = JSON.parseObject(resJson);
//        System.out.println(resJson);
        int code = jsonObject.getInteger("code");
        String msg = jsonObject.get("msg").toString();
        String fileMetadataJson = jsonObject.get("data").toString();
        List<FileMetadata> responseData = JSONObject.parseArray(fileMetadataJson, FileMetadata.class);
//      List<FileMetadata> responseData = (code == 200) ? JSONObject.parseArray(fileMetadataJson, FileMetadata.class) : null;
        return new Result<List<FileMetadata>>().setCode(code).setMessage(msg).setData(responseData);
    }

    /**
     * 更新文件元数据
     *
     * @param fileMetadata
     * @return
     * @throws Exception
     */
    public static Result<FileMetadata> updateFileMetadata(FileMetadata fileMetadata) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.submitTransaction("UpdateFileMetadata", String.valueOf(fileMetadata.getFileMetadataId()),
                String.valueOf(fileMetadata.getFileStatus()), fileMetadata.getFileName(), fileMetadata.getFileDescription());

        String resJson = new String(result, "UTF-8");
        JSONObject jsonObject = JSON.parseObject(resJson);
        int code = jsonObject.getInteger("code");
        String msg = jsonObject.get("msg").toString();
        String fileMetadataJson = jsonObject.get("data").toString();
        FileMetadata responseData = JSONObject.parseObject(fileMetadataJson, FileMetadata.class);
        return new Result<FileMetadata>().setCode(code).setMessage(msg).setData(responseData);
    }

    /**
     * 根据用户id和文件状态获取文件元数据
     *
     * @param userId
     * @param fileStatus
     * @return
     * @throws Exception
     */
    public static Result<List<FileMetadata>> queryFileMetadataByUserId(int userId, int[] fileStatus) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.evaluateTransaction("QueryFileMetadatasByUserId", String.valueOf(userId), JSON.toJSONString(fileStatus));

        String resJson = new String(result, "UTF-8");
        JSONObject jsonObject = JSON.parseObject(resJson);
        int code = jsonObject.getInteger("code");
        String msg = jsonObject.get("msg").toString();
        String fileMetadataJson = jsonObject.get("data").toString();
        List<FileMetadata> responseData = JSONObject.parseArray(fileMetadataJson, FileMetadata.class);
//      List<FileMetadata> responseData = (code == 200) ? JSONObject.parseArray(fileMetadataJson, FileMetadata.class) : null;
        return new Result<List<FileMetadata>>().setCode(code).setMessage(msg).setData(responseData);
    }

    /**
     * 删除文件元数据
     *
     * @param fileMetadataId
     * @return
     * @throws Exception
     */
    public static Result<String> deleteFileMetadata(int fileMetadataId) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.submitTransaction("DeleteFileMetadata", String.valueOf(fileMetadataId));

        String resJson = new String(result, "UTF-8");
        JSONObject jsonObject = JSON.parseObject(resJson);
        int code = jsonObject.getInteger("code");
        String msg = jsonObject.get("msg").toString();
        return new Result<String>().setCode(code).setMessage(msg);
    }

    /**
     * 根据文件元数据唯一Id查询属于该文件的所有分片元数据
     *
     * @param fileMetadataId
     * @return
     * @throws Exception
     */
    public static Result<List<PartitionMetadata>> queryPartitionMetadataByFileMetaId(int fileMetadataId) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.evaluateTransaction("QueryPartitionMetadatasByFileMetaId", String.valueOf(fileMetadataId));


        String resJson = new String(result, "UTF-8");
        JSONObject jsonObject = JSON.parseObject(resJson);
        int code = jsonObject.getInteger("code");
//        System.out.println(resJson);
        String msg = jsonObject.get("msg").toString();
        String partitionJson = jsonObject.get("data").toString();
        List<PartitionMetadata> responseData = JSONObject.parseArray(partitionJson, PartitionMetadata.class);
//      List<FileMetadata> responseData = (code == 200) ? JSONObject.parseArray(fileMetadataJson, FileMetadata.class) : null;
        return new Result<List<PartitionMetadata>>().setCode(code).setMessage(msg).setData(responseData);
    }

    /**
     * 根据用文件状态获取所有用户文件元数据
     *
     * @param fileStatus
     * @return
     * @throws Exception
     */
    public static Result<List<FileMetadata>> queryAllFileMetadatas(int[] fileStatus) throws Exception {
        // connect to the network and invoke the smart contract
        Gateway gateway = connect();
        // get the network and contract
        Network network = gateway.getNetwork("mychannel");
        Contract contract = network.getContract("testStore");

        byte[] result;
        // 查询使用evaluateTransaction，修改和添加使用submitTransaction
        result = contract.evaluateTransaction("QueryAllFileMetadatas", JSON.toJSONString(fileStatus));

        String resJson = new String(result, "UTF-8");
//        System.out.println(resJson);
        JSONObject jsonObject = JSON.parseObject(resJson);
        int code = jsonObject.getInteger("code");
        String msg = jsonObject.get("msg").toString();
        String fileMetadataJson = jsonObject.get("data").toString();
        List<FileMetadata> responseData = JSONObject.parseArray(fileMetadataJson, FileMetadata.class);
//      List<FileMetadata> responseData = (code == 200) ? JSONObject.parseArray(fileMetadataJson, FileMetadata.class) : null;
        return new Result<List<FileMetadata>>().setCode(code).setMessage(msg).setData(responseData);
    }
}
